home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / kerberos / pc / krb_src.lha / KUSER / KSU.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-07  |  9.7 KB  |  377 lines

  1. /*
  2.  * $Source: /mit/kerberos/src/kuser/RCS/ksu.c,v $
  3.  * $Author: jtkohl $
  4.  */
  5.  
  6. /*
  7.  * Copyright (c) 1988 The Regents of the University of California.
  8.  * All rights reserved.
  9.  *
  10.  * Redistribution and use in source and binary forms are permitted
  11.  * provided that the above copyright notice and this paragraph are
  12.  * duplicated in all such forms and that any documentation,
  13.  * advertising materials, and other materials related to such
  14.  * distribution and use acknowledge that the software was developed
  15.  * by the University of California, Berkeley.  The name of the
  16.  * University may not be used to endorse or promote products derived
  17.  * from this software without specific prior written permission.
  18.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  19.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  20.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  21.  */
  22.  
  23. /*
  24.  * Kerberos additions Copyright 1987, 1988 by the Massachusetts Institute
  25.  * of Technology. For copying and distribution information, please see
  26.  * the file <mit-copyright.h>.
  27.  */
  28.  
  29. #ifndef lint
  30. static char rcsid_ksu_c[] =
  31. "$Header: ksu.c,v 4.0 89/01/23 10:00:28 jtkohl Exp $";
  32. #endif lint
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1988 The Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)su.c    5.11 (Berkeley) 12/7/88";
  42. #endif /* not lint */
  43.  
  44. #include <mit-copyright.h>
  45. #include <sys/param.h>
  46. #include <sys/time.h>
  47. #include <sys/resource.h>
  48. #include <syslog.h>
  49. #include <stdio.h>
  50. #include <pwd.h>
  51. #include <grp.h>
  52. #include <krb.h>
  53. #include <netdb.h>
  54. #include <sys/ioctl.h>
  55.  
  56. #ifndef LOG_AUTH
  57. #define LOG_AUTH 0
  58. #endif /* LOG_AUTH */
  59.  
  60. /* for Ultrix and friends ... */
  61. #ifndef MAXHOSTNAMELEN
  62. #define MAXHOSTNAMELEN 64
  63. #endif
  64.  
  65. extern char *krb_err_txt[];
  66. int     kerno;
  67. char    lrealm[REALM_SZ];
  68. char    krbtkfile[128];
  69.  
  70. #define MAXPWSIZE    128    /* Biggest string we accept for a password
  71.                    (includes space for null terminator) */
  72.  
  73. main(argc, argv)
  74.     int argc;
  75.     char **argv;
  76. {
  77.     extern char **environ;
  78.     extern int errno, optind;
  79.     register struct passwd *pwd;
  80.     register char *p, **g;
  81.     struct group *gr;
  82.     uid_t ruid, getuid();
  83. #ifdef NO_GETUSERSHELL
  84.     int ch, fulllogin, fastlogin, prio;
  85. #else
  86.     int asme, ch, fulllogin, fastlogin, prio;
  87. #endif /* NO_GETUSERSHELL */
  88.     enum { UNSET, YES, NO } iscsh = UNSET;
  89.     char *user, *shell, *username, *cleanenv[2], *nargv[4], **np;
  90.     char namebuf[50], shellbuf[MAXPATHLEN];
  91.     char *crypt(), *getpass(), *getenv(), *getlogin(), *rindex(), *strcpy();
  92. #ifdef NOENCRYPTION
  93. #define read_long_pw_string placebo_read_pw_string
  94. #else
  95. #define read_long_pw_string des_read_pw_string
  96. #endif
  97.     int read_long_pw_string();
  98.     char pw_buf[MAXPWSIZE];
  99.     char   *mytty;
  100.   
  101.     mytty = isatty(2) ? (char *) ttyname(2) : "(no tty)";
  102.  
  103.     np = &nargv[3];
  104.     *np-- = NULL;
  105. #ifdef NO_GETUSERSHELL
  106.     fulllogin = fastlogin = 0;
  107. #define GETOPTARG "-flm"
  108. #else
  109.     asme = fulllogin = fastlogin = 0;
  110. #define    GETOPTARG "-fl"
  111. #endif
  112.     while ((ch = getopt(argc, argv, GETOPTARG)) != EOF)
  113.         switch((char)ch) {
  114.         case 'f':
  115.             fastlogin = 1;
  116.             break;
  117.         case '-':
  118.         case 'l':
  119.             fulllogin = 1;
  120.             break;
  121. #ifndef NO_GETUSERSHELL
  122.         case 'm':
  123.             asme = 1;
  124.             break;
  125. #endif
  126.         case '?':
  127.         default:
  128. #ifdef NO_GETUSERSHELL
  129.             fprintf(stderr, "usage: ksu [-fl] [login]\n");
  130. #else
  131.             fprintf(stderr, "usage: ksu [-flm] [login]\n");
  132. #endif /* NO_GETUSERSHELL */
  133.             exit(1);
  134.         }
  135.     argv += optind;
  136.  
  137.     errno = 0;
  138.     prio = getpriority(PRIO_PROCESS, 0);
  139.     if (errno)
  140.         prio = 0;
  141.     (void)setpriority(PRIO_PROCESS, 0, -2);
  142.  
  143.     /* get current login name and shell */
  144.     if ((pwd = getpwuid(ruid = getuid())) == NULL) {
  145.         fprintf(stderr, "ksu: who are you?\n");
  146.         exit(1);
  147.     }
  148.     username = strcpy(namebuf, pwd->pw_name);
  149. #ifndef NO_GETUSERSHELL
  150.     if (asme)
  151.         if (pwd->pw_shell && *pwd->pw_shell)
  152.             shell = strcpy(shellbuf,  pwd->pw_shell);
  153.         else {
  154.             shell = "/bin/sh";
  155.             iscsh = NO;
  156.         }
  157. #endif
  158.  
  159.     /* get target login information */
  160.     user = *argv ? *argv : "root";
  161.     if ((pwd = getpwnam(user)) == NULL) {
  162.         fprintf(stderr, "ksu: unknown login %s\n", user);
  163.         exit(1);
  164.     }
  165.  
  166.     /*
  167.      * Only allow those with kerberos root instances in the /.klogin
  168.      * file to su to root. 
  169.      */
  170.     if (pwd->pw_uid == 0) {
  171.         KTEXT_ST ticket;
  172.         AUTH_DAT authdata;
  173.         char hostname[MAXHOSTNAMELEN], savehost[MAXHOSTNAMELEN];
  174.         unsigned long faddr;
  175.         struct hostent *hp;
  176.  
  177.         /* First lets see if he has a chance! */
  178.         if (krb_get_lrealm(lrealm, 1) != KSUCCESS) {
  179.         fprintf(stderr,"Unable to get local realm\n");
  180.         exit(1);
  181.         }
  182.         if (koktologin(username, lrealm)) {
  183.         fprintf(stderr,"You are not allowed to ksu to root\n");
  184.         exit(1);
  185.         }
  186.         sprintf(krbtkfile, "/tmp/tkt_root_%d", getuid());
  187.         setuid(0);        /* so ticket file has good protection */
  188.         if (read_long_pw_string(pw_buf, sizeof(pw_buf)-1,
  189.                    "Your root instance password: ", 0)) {
  190.         fprintf(stderr,"Error reading password.\n");
  191.         exit(1);
  192.         }
  193.         p = pw_buf;
  194.         setenv("KRBTKFILE", krbtkfile, 1);
  195.         kerno = krb_get_pw_in_tkt(username, "root", lrealm, "krbtgt",
  196.                       lrealm, 2, p);
  197.         bzero(p, strlen(p));
  198.         if (kerno != KSUCCESS) {
  199.         printf("Unable to ksu: %s\n", krb_err_txt[kerno]);
  200.         syslog(LOG_NOTICE|LOG_AUTH, "ksu: BAD SU %s on %s: %s",
  201.                username, mytty, krb_err_txt[kerno]);
  202.         exit(1);
  203.         }
  204.         setpriority(PRIO_PROCESS, 0, -2);
  205.         /*
  206.          * Now use the ticket for something useful, to make sure
  207.          * it is valid.
  208.          */
  209.         if (gethostname(hostname, sizeof(hostname)) == -1) {
  210.         perror("cannot retrieve hostname");
  211.         dest_tkt();
  212.         exit(1);
  213.         }
  214.         (void) strncpy(savehost, krb_get_phost(hostname),
  215.                sizeof(savehost));
  216.         savehost[sizeof(savehost)-1] = 0;
  217.  
  218.         kerno = krb_mk_req(&ticket, "rcmd", savehost, lrealm, 33);
  219.         if (kerno == KDC_PR_UNKNOWN) {
  220.         printf("Warning: tgt not verified\n");
  221.         syslog(LOG_NOTICE|LOG_AUTH, "ksu: %s on %s: tgt not verified",
  222.                username, mytty);
  223.         } else if (kerno != KSUCCESS) {
  224.         printf("Unable to use tgt: %s\n", krb_err_txt[kerno]);
  225.         syslog(LOG_NOTICE|LOG_AUTH, "ksu: failed su: %s on %s: %s",
  226.                username, mytty, krb_err_txt[kerno]);
  227.         dest_tkt();
  228.         exit(1);
  229.         } else {
  230.         if (!(hp = gethostbyname(hostname))) {
  231.             printf("Unable to get address of %s\n",hostname);
  232.             dest_tkt();
  233.             exit(1);
  234.         }
  235.         bcopy((char *)hp->h_addr, (char *) &faddr, sizeof(faddr));
  236.         if ((kerno = krb_rd_req(&ticket, "rcmd", savehost,
  237.                     faddr, &authdata, "")) != KSUCCESS) {
  238.             printf("Unable to verify rcmd ticket: %s\n",
  239.                krb_err_txt[kerno]);
  240.             syslog(LOG_NOTICE|LOG_AUTH, "ksu: failed su: %s on %s: %s",
  241.                username, mytty, krb_err_txt[kerno]);
  242.             dest_tkt();
  243.             exit(1);
  244.         }        
  245.         }
  246.         printf("Don't forget to kdestroy before exiting the root shell.\n");
  247.     } else
  248.     /* if target requires a password, verify it */
  249.     if (ruid && *pwd->pw_passwd) {
  250.         p = getpass("Password:");
  251.         if (strcmp(pwd->pw_passwd, crypt(p, pwd->pw_passwd))) {
  252.             fprintf(stderr, "Sorry\n");
  253.             if (pwd->pw_uid == 0)
  254.                 syslog(LOG_CRIT|LOG_AUTH, "ksu: BAD SU %s on %s", username, mytty);
  255.             exit(1);
  256.         }
  257.     }
  258.  
  259. #ifndef NO_GETUSERSHELL
  260.     if (asme) {
  261.         /* if asme and non-standard target shell, must be root */
  262.         if (!chshell(pwd->pw_shell) && ruid) {
  263.             fprintf(stderr, "ksu: Permission denied.\n");
  264.             dest_tkt();
  265.             exit(1);
  266.         }
  267.     }
  268.     else
  269. #endif
  270.     if (pwd->pw_shell && *pwd->pw_shell) {
  271.         shell = pwd->pw_shell;
  272.         iscsh = UNSET;
  273.     } else {
  274.         shell = "/bin/sh";
  275.         iscsh = NO;
  276.     }
  277.  
  278.     /* if we're forking a csh, we want to slightly muck the args */
  279.     if (iscsh == UNSET) {
  280.         if (p = rindex(shell, '/'))
  281.             ++p;
  282.         else
  283.             p = shell;
  284.         iscsh = strcmp(p, "csh") ? NO : YES;
  285.     }
  286.  
  287.     /* set permissions */
  288.     if (setgid(pwd->pw_gid) < 0) {
  289.         perror("ksu: setgid");
  290.         dest_tkt();
  291.         exit(1);
  292.     }
  293.     if (initgroups(user, pwd->pw_gid)) {
  294.         fprintf(stderr, "ksu: initgroups failed\n");
  295.         dest_tkt();
  296.         exit(1);
  297.     }
  298.     if (setuid(pwd->pw_uid) < 0) {
  299.         perror("ksu: setuid");
  300.         dest_tkt();
  301.         exit(1);
  302.     }
  303.  
  304. #ifndef NO_GETUSERSHELL
  305.     if (!asme) {
  306. #endif
  307.         if (fulllogin) {
  308.             p = getenv("TERM");
  309.             cleanenv[0] = "PATH=:/usr/ucb:/bin:/usr/bin";
  310.             cleanenv[1] = NULL;
  311.             environ = cleanenv;
  312.             (void)setenv("TERM", p, 1);
  313.             if (chdir(pwd->pw_dir) < 0) {
  314.                 fprintf(stderr, "ksu: no directory\n");
  315.                 dest_tkt();
  316.                 exit(1);
  317.             }
  318.         }
  319.         if (fulllogin || pwd->pw_uid)
  320.             (void)setenv("USER", pwd->pw_name, 1);
  321.         (void)setenv("HOME", pwd->pw_dir, 1);
  322.         (void)setenv("SHELL", shell, 1);
  323. #ifndef NO_GETUSERSHELL
  324.     }
  325. #endif
  326.  
  327.     if (iscsh == YES) {
  328.         if (fastlogin)
  329.             *np-- = "-f";
  330. #ifndef NO_GETUSERSHELL
  331.         if (asme)
  332.             *np-- = "-m";
  333. #endif
  334.     }
  335.  
  336.     /* csh strips the first character... */
  337.     *np = fulllogin ? "-ksu" : iscsh == YES ? "_ksu" : "ksu";
  338.  
  339.     if (pwd->pw_uid == 0)
  340.         syslog(LOG_NOTICE|LOG_AUTH, "ksu: %s on %s",
  341.             username, mytty);
  342.  
  343.     (void)setpriority(PRIO_PROCESS, 0, prio);
  344.  
  345.     execv(shell, np);
  346.     fprintf(stderr, "ksu: no shell.\n");
  347.     dest_tkt();
  348.     exit(1);
  349. }
  350.  
  351. #ifndef NO_GETUSERSHELL
  352. chshell(sh)
  353.     char *sh;
  354. {
  355.     char *cp, *getusershell();
  356.  
  357.     while ((cp = getusershell()) != NULL)
  358.         if (!strcmp(cp, sh))
  359.             return(1);
  360.     return(0);
  361. }
  362. #endif /* NO_GETUSERSHELL */
  363.  
  364. koktologin(name, realm)
  365.     char   *name;
  366.     char   *realm;
  367. {
  368.     struct auth_dat kdata_st;
  369.     AUTH_DAT *kdata = &kdata_st;
  370.     /* Cons together an AUTH_DAT structure for kuserok */
  371.     bzero((caddr_t) kdata, sizeof(*kdata));
  372.     strcpy(kdata->pname, name);
  373.     strcpy(kdata->pinst, "root");
  374.     strcpy(kdata->prealm, realm);
  375.     return (kuserok(kdata, "root"));
  376. }
  377.